package com.jungle.framework.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkb;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@SuppressWarnings("rawtypes")
@MappedJdbcTypes(value = JdbcType.OTHER)
@MappedTypes(value = {Geometry.class})
public class GeometryTypeHandler extends BaseTypeHandler<Geometry> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType)
        throws SQLException {
    }

    @Override
    public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return fromMysqlWkb(rs.getBytes(columnName));
    }

    @Override
    public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return fromMysqlWkb(rs.getBytes(columnIndex));
    }

    @Override
    public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return fromMysqlWkb(cs.getBytes(columnIndex));
    }

    private Geometry fromMysqlWkb(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        byte[] geomBytes = ByteBuffer.allocate(bytes.length - 4).order(ByteOrder.LITTLE_ENDIAN)
            .put(bytes, 4, bytes.length - 4).array();
        return Wkb.fromWkb(org.geolatte.geom.ByteBuffer.from(geomBytes));
    }
}
